package com.ruoyi.stock2.thread.aboutDownloadData;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.net.UnknownHostException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import com.ruoyi.stock2.domain.*;
import com.ruoyi.stock2.service.IDownTradedataFailService;
import org.jsoup.Connection.Response;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.select.Elements;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.util.StringUtils;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.stock2.mapper.DownTradedataScheduleMapper;
import com.ruoyi.stock2.mapper.STOCKMapper;
import com.ruoyi.stock2.mapper.TRADEDATAMapper;
import com.ruoyi.stock2.utils.DateUtils2;

//数据从 163网站下载
public class DownLoadStockTradeData2 {
    private static final Logger log = LoggerFactory.getLogger(DownLoadStockTradeData2.class);
    DownTradedataScheduleMapper downLoadTradedataScheduleMapper;
    STOCKMapper stockMapper;
    TRADEDATAMapper tradedataMapper;
    UpdateStocksSymbolDataService updateStocksSymbolDataService;
    IDownTradedataFailService iDownTradedataFailService;
    String now163Date = null;

    public String getNow163Date() {
        return now163Date;
    }

    public void setNow163Date(String now163Date) {
        this.now163Date = now163Date;
    }

    //单例实现 涉及到任务状态
    public static DownLoadStockTradeData2 getInstance() {
        return Singtonle.instance;
    }

    private static class Singtonle {
        private static DownLoadStockTradeData2 instance = new DownLoadStockTradeData2();
    }


    boolean whileflag11 = true;
    boolean whileflag12 = true;

    public void run() {
        //初始化实例
        downLoadTradedataScheduleMapper = (DownTradedataScheduleMapper) SpringUtils.getBean(DownTradedataScheduleMapper.class);
        tradedataMapper = (TRADEDATAMapper) SpringUtils.getBean(TRADEDATAMapper.class);
        stockMapper = (STOCKMapper) SpringUtils.getBean(STOCKMapper.class);
        updateStocksSymbolDataService = (UpdateStocksSymbolDataService) SpringUtils.getBean(UpdateStocksSymbolDataService.class);
        iDownTradedataFailService = (IDownTradedataFailService) SpringUtils.getBean(IDownTradedataFailService.class);
        step1();
        downLoadTradedataScheduleMapper.updateDownTradedataSchedule(new DownTradedataSchedule("download_schedule", "000000"));
        downLoadTradedataScheduleMapper.updateDownTradedataSchedule(new DownTradedataSchedule("delete_tradedata", "000000"));
    }

    public void step1() {
        //获取系统已经完成下载数据日期
        String lastDownLoadDateFromSina = downLoadTradedataScheduleMapper.selectDownTradedataScheduleByName("lastDownLoadFromSinaDate").getValue();
        String diyDownloadDate = downLoadTradedataScheduleMapper.selectDownTradedataScheduleByName("diyDownloadDate").getValue();
        if (StringUtils.isEmpty(diyDownloadDate) || "null".equals(diyDownloadDate)) {
            now163Date = CheckSourceReady1.checkSourceReady();
        } else {//如果不为空，表示允许交易数据下载到用户自己设定的日期，如下载数据已经隔夜了，需要暂时中断，回头再下载
            now163Date = diyDownloadDate;
        }
        log.warn("### now163Date:"+now163Date);
        //获取sinajs已经完成数据日期
        if (now163Date!=null && !"".equals(now163Date) && now163Date.compareTo(lastDownLoadDateFromSina) > 0) {

            //中断后重新开始下载的处理 begin
            DownTradedataSchedule ac = downLoadTradedataScheduleMapper.selectDownTradedataScheduleByName("download_schedule");
            if (!ac.getValue().equals("000000")) {
                downLoadTradedataScheduleMapper.updateDownTradedataSchedule(new DownTradedataSchedule("delete_tradedata", "开始删除" + ac.getValue() + " " + lastDownLoadDateFromSina + "日之后日期的数据"));
                TRADEDATA tradeDatakey = new TRADEDATA();
                tradeDatakey.setSymbol(ac.getValue());
                tradeDatakey.setDatetime(DateUtils2.formatStringToDate(lastDownLoadDateFromSina, "yyyy-MM-dd"));
                //删除股票代码大于等于symbol并且日期大于lastDownLoadDateFromSina 的数据
                tradedataMapper.deleteByPrimaryKey(tradeDatakey);
                downLoadTradedataScheduleMapper.updateDownTradedataSchedule(new DownTradedataSchedule("delete_tradedata", "完成删除" + ac.getValue() + " " + lastDownLoadDateFromSina + "日之后日期的数据"));
            }
            //中断后重新开始下载的处理 end

            downLoadTradeData(lastDownLoadDateFromSina, now163Date);

        } else {
            DownTradedataSchedule dts = new DownTradedataSchedule("sinadata_ready?", "交易历史数据未准备好");
            dts.setRemark("交易历史数据未准备好或者有自定义日期");
            downLoadTradedataScheduleMapper.updateDownTradedataSchedule(dts);
        }

    }


    public void downLoadTradeData(String lastDownLoadDateFromSina, String nowDate) {

        List<STOCK> stocks = stockMapper.selectSTOCKList(null);//from stock order by SYMBOL ASC
        DownTradedataSchedule ac = downLoadTradedataScheduleMapper.selectDownTradedataScheduleByName("download_schedule");
        for (int k = 0; k < stocks.size(); k++) {// list遍历 非已退市
            if (stocks.get(k).getSymbol().compareTo(ac.getValue()) < 0) {
                continue;
            }
            DownTradedataSchedule ac1 = downLoadTradedataScheduleMapper.selectDownTradedataScheduleByName("download_schedule");
            ac1.setValue(stocks.get(k).getSymbol());
            downLoadTradedataScheduleMapper.updateDownTradedataSchedule(ac1);

            whileflag11 = true;
            whileflag12 = true;
            boolean nextf = false;

            int i = 0 ;
            while (whileflag11 && i<2) {// 循环调用下载程序直到成功
                if(i>=1){
                    log.warn("再次抓取! symbol:"+stocks.get(k).getSymbol() + " 日期 " +  lastDownLoadDateFromSina.replace("-", "") + "--" + nowDate.replace("-", ""));
                }
                nextf = downloadData5_31(stocks.get(k).getSymbol(), lastDownLoadDateFromSina.replace("-", ""), nowDate.replace("-", ""));
                //非全量下载时 使用的时间间隔
                try {
                    Thread.sleep(4000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                i++;

            }
            if(!nextf){
                i = 0;
                while (whileflag12 && i<2 ) {// 循环调用下载程序直到成功
                    if(i>=1){
                        log.warn("再次抓取! symbol:"+stocks.get(k).getSymbol() + "日期：" + nowDate.replace("-", ""));
                    }
                    downloadData1_4(stocks.get(k).getSymbol(), nowDate);
                    //非全量下载时 使用的时间间隔
                    try {
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    i++;
                }
            }

        }
    }

    /**
     * http://quotes.money.163.com/service/chddata.html?code=1000001&start=20200601&end=&fields=TCLOSE;HIGH;LOW;TOPEN;LCLOSE;CHG;PCHG;TURNOVER;VOTURNOVER;VATURNOVER;TCAP;MCAP
     * http://quotes.money.163.com/service/chddata.html?code=1000001&start=20200601&end=20200602&fields=TCLOSE;HIGH;LOW;TOPEN;LCLOSE;CHG;PCHG;TURNOVER;VOTURNOVER;VATURNOVER;TCAP;MCAP
     * @param symbol 000001
     * @param lastDownLoadDateFromSina 20191201
     * @param nowDate 20191202
     */
    private boolean downloadData5_31(String symbol, String lastDownLoadDateFromSina, String nowDate) {

        boolean nextf = false;

        String code = "1" + symbol;

        if ("999001".equals(symbol)) {
            code = "1399001";
        }
        if ("900001".equals(symbol)) {
            code = "0000001";
        }
        if ("999006".equals(symbol)) {
            code = "1399102";
        }
        if (symbol.startsWith("6")) {
            code = "0" + symbol;
        }
        BufferedReader bufferedReader = null;
        List<TRADEDATA> temp1 = new ArrayList<TRADEDATA>(30);
        int csize = 100;
        if(lastDownLoadDateFromSina.startsWith("2004")){
            csize = 4000;
        }
        List<TRADEDATA> concurrentLinkedQueue = new ArrayList<TRADEDATA>(csize);

        try {
            Response resultImageResponse = Jsoup.connect("http://quotes.money.163.com/service/chddata.html?code=" + code + "&start=" + lastDownLoadDateFromSina + "&end=" + nowDate + "&fields=TCLOSE;HIGH;LOW;TOPEN;LCLOSE;CHG;PCHG;TURNOVER;VOTURNOVER;VATURNOVER;TCAP;MCAP")
                    .ignoreContentType(true)
                    .execute();

            bufferedReader = new BufferedReader(new InputStreamReader(resultImageResponse.bodyStream(), "GBK"));
            String s;
           /*
            * 日期	股票代码	名称	收盘价	最高价	最低价	开盘价	前收盘	涨跌额	涨跌幅	换手率	成交量	成交金额	总市值	流通市值	成交笔数
			2019/9/10	'399102	创业板综	2060.6597	2068.2884	2046.2912	2066.6962	2063.7882	-3.1285	-0.1516		10976119782	1.49E+11			8201387
			2019/9/9	'399102	创业板综	2063.7882	2063.7882	2012.9203	2023.4389	2007.3455	56.4427	2.8118		11239712033	1.53E+11			8089390
            */
            s=bufferedReader.readLine();
            while ((s = bufferedReader.readLine()) != null) {
                String[] e = s.split(",");
                if (e.length>10 && !"None".equals(e[8]) && !"None".equals(e[9]) && !"0.0".equals(e[3])) {

                    TRADEDATA tradeData = new TRADEDATA();
                    if(e[0].contains("-")){
                        tradeData.setDatetime(DateUtils2.formatStringToDate(e[0], "yyyy-MM-dd"));
                    }else{
                        tradeData.setDatetime(DateUtils2.formatStringToDate(e[0], "yyyyMMdd"));
                    }
                    tradeData.setSymbol(symbol);


                    if (!"None".equals(e[3]) && !"0.0".equals(e[3]))
                        tradeData.setCloseprice(new BigDecimal(e[3].replace(",", "")));
                    else
                        continue;
                    if (!"None".equals(e[4]) && !"0.0".equals(e[4]))
                        tradeData.setHighprice(new BigDecimal(e[4].replace(",", "")));
                    else
                        continue;
                    if (!"None".equals(e[5]) && !"0.0".equals(e[5]))
                        tradeData.setLowprice(new BigDecimal(e[5].replace(",", "")));
                    else
                        continue;
                    if (!"None".equals(e[6]) && !"0.0".equals(e[6]))
                        tradeData.setDateopenprice(new BigDecimal(e[6].replace(",", "")));
                    else
                        continue;


                    if (!"None".equals(e[11]) && !"0.0".equals(e[11]))
                        tradeData.setVolume(new BigDecimal(e[11].replace(",", "")).divide(new BigDecimal(100), 0, BigDecimal.ROUND_HALF_UP));
                    else
                        continue;

                    if (!"None".equals(e[12]) && !"0.0".equals(e[12]))
                        tradeData.setAmount(new BigDecimal(e[12].replace(",", "")).divide(new BigDecimal(10000), 0, BigDecimal.ROUND_HALF_UP));
                    else
                        continue;

                    if(lastDownLoadDateFromSina.startsWith("2004")){
                        concurrentLinkedQueue.add(tradeData);
                    }else{
                        TRADEDATA key = new TRADEDATA(symbol, tradeData.getDatetime());
                        List<TRADEDATA> tradeData1 = tradedataMapper.selectTRADEDATAList(key);
                        if (tradeData1.size() == 0) {
                            concurrentLinkedQueue.add(tradeData);
                        }
                    }


                }

            }

            if (concurrentLinkedQueue.size() > 0) {
                int sizec = concurrentLinkedQueue.size()-1;
                TRADEDATA obj = concurrentLinkedQueue.get(0);
                Date objdate = obj.getDatetime();
                String objdatetostrd = DateUtils2.formatDateToString(objdate,"yyyyMMdd");
                if(objdatetostrd.equals(nowDate)){
                    nextf = true;
                }
                for (int i = sizec; i >= 0; i--) {
                    temp1.add(concurrentLinkedQueue.get(i));
                    if (temp1.size() == 30) {
                        tradedataMapper.insertTRADEDATA2(temp1);
                        temp1.clear();
                    }
                }

                if (temp1.size() > 0) {
                    tradedataMapper.insertTRADEDATA2(temp1);
                    temp1.clear();
                }
            }

            whileflag11 = false;
            concurrentLinkedQueue = null;
        } catch (java.net.SocketTimeoutException e1) {
            e1.printStackTrace();
            log.warn("下载数据报错downloadData5_31() SocketTimeoutException:symbol:"+symbol + ", lastDownLoadDateFromSina:" + lastDownLoadDateFromSina + ", nowDate:"+  nowDate);
        } catch (UnknownHostException e1) {
            e1.printStackTrace();
            insertFailSymbol(symbol, lastDownLoadDateFromSina, nowDate);
            log.warn("下载数据报错downloadData5_31() UnknownHostException:symbol: "+symbol + ", lastDownLoadDateFromSina:" + lastDownLoadDateFromSina + ", nowDate:"+  nowDate);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (bufferedReader != null) {
                    bufferedReader.close();
                }
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        return nextf;
    }

    /**
     *
     * @param symbol
     * @param endDate 2019-12-01
     */
//    http://quotes.money.163.com/trade/lsjysj_zhishu_399001.html?year=2019&season=4
//    http://quotes.money.163.com/trade/lsjysj_000001.html?year=2019&season=4
    //http://quotes.money.163.com/service/chddata.html?code=000001&start=20200601&end=20200601&fields=TCLOSE;HIGH;LOW;TOPEN;LCLOSE;CHG;PCHG;TURNOVER;VOTURNOVER;VATURNOVER;TCAP;MCAP"
    private void downloadData1_4(String symbol, String endDate) {
        if ("999001".equals(symbol)) {
            symbol = "zhishu_399001";
        }
        if ("900001".equals(symbol)) {
            symbol = "zhishu_000001";
        }
        if ("999006".equals(symbol)) {
            symbol = "zhishu_399102";
        }

        SimpleDateFormat sFormat = new SimpleDateFormat("yyyy-MM-dd");
        Date date = new Date();

        String jidu = String.valueOf((Integer.valueOf(sFormat.format(date).split("-")[1]) - 1) / 3 + 1);

        Document doc;
        try {
            String url = "http://quotes.money.163.com/trade/lsjysj_" + symbol + ".html?year=" + sFormat.format(date).split("-")[0] + "&season=" + jidu;
            doc = Jsoup.connect(url).timeout(10000).get();
            if(!doc.getElementsByClass("table_bg001 border_box limit_sale").isEmpty()){
                if(!doc.getElementsByClass("table_bg001 border_box limit_sale").get(0).getElementsByTag("tbody").isEmpty()){
                    Elements es = doc.getElementsByClass("table_bg001 border_box limit_sale").get(0)
                            .getElementsByTag("tbody").get(0)
                            .getElementsByTag("tr");
                    for (int i = es.size() - 1; i >= 0; i--) {
                        Elements e = es.get(i).getElementsByTag("td");

                        TRADEDATA tradeData = new TRADEDATA();
                        if(e.get(0).text().contains("-")){
                            tradeData.setDatetime(DateUtils2.formatStringToDate(e.get(0).text(), "yyyy-MM-dd"));
                        }else{
                            tradeData.setDatetime(DateUtils2.formatStringToDate(e.get(0).text(), "yyyyMMdd"));
                        }

                        tradeData.setSymbol(symbol);
                        if(e.get(0).text().compareTo(endDate)<=0){
                            if (!"None".equals(e.get(1).text()) && !"0.0".equals(e.get(1).text()))
                                tradeData.setDateopenprice(new BigDecimal(e.get(1).text().replace(",", "")));
                            else
                                continue;
                            if (!"None".equals(e.get(2).text()) && !"0.0".equals(e.get(2).text()))
                                tradeData.setHighprice(new BigDecimal(e.get(2).text().replace(",", "")));
                            else
                                continue;
                            if (!"None".equals(e.get(3).text()) && !"0.0".equals(e.get(3).text()))
                                tradeData.setLowprice(new BigDecimal(e.get(3).text().replace(",", "")));
                            else
                                continue;
                            if (!"None".equals(e.get(4).text()) && !"0.0".equals(e.get(4).text()))
                                tradeData.setCloseprice(new BigDecimal(e.get(4).text().replace(",", "")));
                            else
                                continue;

                            if (!"None".equals(e.get(7).text()) && !"0.0".equals(e.get(7).text()))
                                tradeData.setVolume(new BigDecimal(e.get(7).text().replace(",", "")));
                            else
                                continue;

                            if (!"None".equals(e.get(8).text()) && !"0.0".equals(e.get(8).text()))
                                tradeData.setAmount(new BigDecimal(e.get(8).text().replace(",", "")));
                            else
                                continue;

                            TRADEDATA key = new TRADEDATA(symbol, tradeData.getDatetime());
                            List<TRADEDATA> tradeData1 = tradedataMapper.selectTRADEDATAList(key);
                            if (tradeData1.size() == 0) {
                                tradedataMapper.insertTRADEDATA(tradeData);
                            }
                        }
                    }
                }
            }

            whileflag12 = false;
        } catch (java.net.SocketTimeoutException e1) {
            e1.printStackTrace();
            log.warn("下载数据报错 downloadData1_4() SocketTimeoutException：symbol:"+symbol + ", endDate:" + endDate);
        } catch (java.net.UnknownHostException e1) {
            e1.printStackTrace();
            log.warn("下载数据报错 downloadData1_4() UnknownHostException：symbol:"+symbol + ", endDate:" + endDate );
        } catch (Exception e1) {
            e1.printStackTrace();
        }
    }

    public void insertFailSymbol(String symbol, String from, String to){
        DownTradedataFail dtf = iDownTradedataFailService.selectDownTradedataFailById(symbol);
        if(dtf==null){
            dtf = new DownTradedataFail();
            dtf.setSymbol(symbol);
            dtf.setFromdate(from);
            dtf.setTodate(to);
            iDownTradedataFailService.insertDownTradedataFail(dtf);
        }
    }
}
